﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

using Game.Common;
using Game.Map;
using Game.Map.Extensions;
using Game.Terrain;

namespace Game.Surface
{
    public class SurfaceControl : UserControl
    {
        public event EventHandler<GameMapEventArgs> Click;

        readonly GameCanvas _Canvas;
        readonly IGameMapView _GameMapView;
        readonly Dictionary<Point, SurfaceTopField> _Fields = new Dictionary<Point, SurfaceTopField>();
        
        readonly ScaleTransform _Transform = new ScaleTransform();
        readonly TranslateTransform _TranslateTransform = new TranslateTransform();
        readonly TransformGroup _TransformGroup = new TransformGroup();

        Point _MouseDown;
        Point _MouseDownScreen;
        Point _CanvasOrigin;
        bool _MouseCapture;
        bool _MapCanMove = true;
        double _Scale = 1;

        public SurfaceControl()
            : this(Factory.Create())
        {
            
        }

        public SurfaceControl(IGameMap map)
        {
            _Canvas = new GameCanvas {RenderTransform = _TransformGroup};
            var grid = new Grid();
            grid.Children.Add(_Canvas);
            Content = grid;
            
            Width = 2200;
            Height = 2200;
            
            MouseMove += OnMouseMove;
            MouseLeftButtonDown += OnMouseDown;
            MouseLeftButtonUp += OnMouseUp;
            MouseLeave += OnMouseLeave;
            
            _GameMapView = map.Views[HumanPlayer.Player];
            
            _TranslateTransform.X = -500;
            _TranslateTransform.Y = -500;
            _Canvas.OriginX = -500;
            _Canvas.OriginY = -500;
            _TransformGroup.Children.Add(_Transform);
            _TransformGroup.Children.Add(_TranslateTransform);
                
            Init();
        }
        
        public virtual void Start()
        {
        }

        public bool MapCanMove
        {
            get { return _MapCanMove; }
            set { _MapCanMove=value; }
        }

        protected TransformGroup Transform
        {
            get { return _TransformGroup; }
        }

        public GameCanvas GameCanvas
        {
            get { return _Canvas; }
        }
        
        public IGameMapView GameMapView
        {
            get { return _GameMapView; }
        }

        public Dictionary<Point, SurfaceTopField> Fields
        {
            get { return _Fields; }
        }

        public double GameScale
        {
            get { return _Scale; }
            set 
            { 
                _Scale=value;
                _Transform.ScaleX = _Scale;
                _Transform.ScaleY = _Scale;
                _Transform.CenterX = (Width / 2);
                _Transform.CenterY = (Height / 2);
            }
        }

        void Init()
        {
            foreach(var field in _GameMapView.ViewFields)
            {
                AbstractField cloud = null;
                AbstractField top = null;
                {
                    var f = new SurfaceCloudField(field);
                    GameCanvas.SetGameLeft(f, f.Left);
                    GameCanvas.SetGameTop(f, f.Top);
                    GameCanvas.SetZIndex(f, 10);
                    _Canvas.Children.Add(f);
                    cloud = f;
                }
                {
                    var f = new SurfaceTopField(field, cloud);
                    GameCanvas.SetGameLeft(f, f.Left);
                    GameCanvas.SetGameTop(f, f.Top);
                    GameCanvas.SetZIndex(f, 0);
                    _Canvas.Children.Add(f);
                    top = f;
                    
                    var p = new Point(field.Point.X, field.Point.Y);
                    _Fields.Add(p, f);
                }
//                {
//                    var f = new SurfaceSelectedField(field);
//                    GameCanvas.SetGameLeft(f, f.Left);
//                    GameCanvas.SetGameTop(f, f.Top);
//                    GameCanvas.SetZIndex(f, 15);
//                    _Canvas.Children.Add(f);
//                }
//                {
//                    var f = CreateSurfaceField(field, top, cloud);
//                    GameCanvas.SetGameLeft(f, f.Left);
//                    GameCanvas.SetGameTop(f, f.Top);
//                    GameCanvas.SetZIndex(f, 1);
//                    _Canvas.Children.Add(f);
//
//                    var p = new Point(field.Point.X, field.Point.Y);
//                    _Fields.Add(p, f);
//                }

            }
        }
        
//        protected virtual SurfaceField CreateSurfaceField(
//            IMapFieldView field,
//            AbstractField top,
//            AbstractField cloud)
//        {
//            return new SurfaceField(field, top, cloud);
//        }

        void OnMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (!_MapCanMove)
            {
                return;
            }

            _MouseDownScreen = e.GetPosition(null);
            _MouseDown = e.GetPosition(this);
            _MouseCapture = true;
            _CanvasOrigin = new Point(_Canvas.OriginX, _Canvas.OriginY);
            CaptureMouse();
        }
        
        void OnMouseUp(object sender, MouseButtonEventArgs e)
        {
            if (!_MouseCapture)
            {
                return;
            }

            _MouseCapture = false;
            
            var screen = e.GetPosition(null);
            
            double dx = Math.Abs(screen.X - _MouseDownScreen.X);
            double dy = Math.Abs(screen.Y - _MouseDownScreen.Y);
            if (dx < 3 && dy < 3)
            {
                AbstractField field = _Canvas.HitTest(e);
                if (field != null)
                {
                    _GameMapView.ClickX().DoClick(field.MapField);
                    
                    if (Click != null)
                    {
                        var args = new GameMapEventArgs {MapField = field.MapField};
                        Click(this, args);
                    }
                }
            }
            
            ReleaseMouseCapture();
        }
        
        void OnMouseLeave(object sender, MouseEventArgs e)
        {
            if (!_MouseCapture)
            {
                return;
            }

            _MouseCapture = false;
            ReleaseMouseCapture();
        }
        
        void OnMouseMove(object sender, MouseEventArgs e)
        {
            if (!_MouseCapture)
            {
                return;
            }

            var p = e.GetPosition(this);
            double toLeft = _CanvasOrigin.X + (p.X - _MouseDown.X);
            double toTop = _CanvasOrigin.Y + (p.Y - _MouseDown.Y);

            _Canvas.OriginX = toLeft;
            _Canvas.OriginY = toTop;
            _TranslateTransform.X = toLeft;
            _TranslateTransform.Y = toTop;
        }
        
    }
    
}
